package com.notary.seal;

import cn.hutool.core.text.UnicodeUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.notary.data.request.SignContractRequestDTO;
import com.notary.data.request.SignerRequestDTO;
import com.notary.entity.Deposit;
import com.notary.entity.SysConfig;
import com.notary.entity.po.DepositDTO;
import com.notary.entity.po.GzcRegisterDTO;
import com.notary.entity.vo.JsonResult;
import com.notary.service.DepositService;
import com.notary.service.SysPlatformOpeningRecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


@Service
@Slf4j
public class SealRequestServiceImpl implements SealRequestService {

    @Value("${dzqSystem.dzqToken}")
    private String dzqToken;
    @Value("${dzq.firmRegister}")
    private String firmRegister;
    @Value("${dzq.personalRegister}")
    private String personalRegister;
    @Value("${dzq.contractApply}")
    private String contractApply;
    @Value("${dzq.fileContractPrimary}")
    private String fileContractPrimary;
    @Value("${dzq.downloadNotaryByNo}")
    private String downloadNotaryByNo;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Value("${execute.updateStatus}")
    private String updateStatusUrl;
    @Value("${execute.signContract}")
    private String signContractUrl;
    @Value("${execute.createSigner}")
    private String createSignerUrl;
    @Value("${execute.updateCertificate}")
    private String updateCertificateUrl;
    @Value("${office.code}")
    private String officeCode;
    @Value("${execute.notaryRegisterUrl}")
    private String notaryRegisterUrl;
    @Value("${execute.attestationUrl}")
    private String attestationUrl;
    @Value("${deposit.verify}")
    private String verifyUrl;
    @Value("${deposit.download}")
    private String downloadUrl;
    @Value("${deposit.depositList}")
    private String depositListUrl;
    @Autowired
    private SysPlatformOpeningRecordService sysPlatformOpeningRecordService;
    @Autowired
    private DepositService depositService;

    @Override
    public String getDzqToken() {
        String token = redisTemplate.opsForValue().get("dzqToken");
        if (StringUtils.isNoneBlank(token)) {
            log.info("获取电子签token:{}", token);
            return token;
        }
        JsonResult config = sysPlatformOpeningRecordService.getConfig();
        if (Objects.equals("200", config.getCode())) {
            ObjectMapper objectMapper = new ObjectMapper();
            SysConfig sysConfig = objectMapper.convertValue(config.getData(), SysConfig.class);
            if (sysConfig != null && StringUtils.isNotBlank(sysConfig.getAppid()) && StringUtils.isNotBlank(sysConfig.getSecret())) {
                long ts = System.currentTimeMillis();
                String nonce = DigestUtils.md5Hex(System.currentTimeMillis() + "");
                String signSrc = "nonce" + nonce + "ts" + ts + "appId" + sysConfig.getAppid() + "appSecret" + sysConfig.getSecret();
                String sign = DigestUtils.md5Hex(signSrc);
                JSONObject body = new JSONObject();
                body.put("appId", sysConfig.getAppid());
                body.put("sign", sign);
                body.put("nonce", nonce);
                body.put("ts", ts);
                String result = HttpUtil.createPost(dzqToken).body(body.toString(), "application/json;utf-8").execute().body();
                JSONObject json = JSONUtil.parseObj(result);
                if (StringUtils.equals(json.getStr("code"), "200")) {
                    token = json.getStr("data");
                    redisTemplate.opsForValue().set("dzqToken", token, 90L, TimeUnit.MINUTES);
                }
                log.info("获取电子签token:{}", token);
                return token;
            }
            return null;
        }
        return null;
    }

    @Override
    public JsonResult firmRegister(FirmRegisterRequest registerRequest) {
        String token = getDzqToken();
        String result = HttpUtil.createPost(firmRegister)
                .header("Authorization", token)
                .body(JSONUtil.toJsonStr(registerRequest), "application/json")
                .execute()
                .body();
        log.info("获取企业签章id{}", result);
        return JSONUtil.toBean(result, JsonResult.class);
    }

    @Override
    public JsonResult personalRegister(PersonalRegisterRequest personalRegisterRequest) {
        String token = getDzqToken();
        log.info("token:{}", token);
        log.info("personalRegisterRequest:{}", personalRegisterRequest);
        String result = HttpUtil.createPost(personalRegister)
                .header("Authorization", token)
                .body(JSONUtil.toJsonStr(personalRegisterRequest), "application/json")
                .execute()
                .body();
        log.info("获取个人签名id{}", result);
        System.out.println(JSONUtil.toJsonStr(personalRegisterRequest));
        return JSONUtil.toBean(result, JsonResult.class);
    }

    @Override
    public JsonResult contractApply(File file) {
        String token = getDzqToken();
        String result = HttpUtil.createPost(contractApply)
                .header("Authorization", token)
                .form("file", file)
                .execute()
                .body();
        return JSONUtil.toBean(result, JsonResult.class);
    }

    @Override
    public InputStream downloadNotaryByNo(String contractNo) {
        String token = getDzqToken();
        return HttpUtil.createPost(downloadNotaryByNo)
                .header("Authorization", token)
                .form("contractNo", contractNo).execute().bodyStream();
    }

    @Override
    public JsonResult fileContractPrimary(String contractNo, String template) {
        log.info("盖章请求参数:{}", contractNo);
        String token = getDzqToken();
        if (StringUtils.isEmpty(template)) {
            template = "{\"isShow\":\"0\",\"signatories\":[{\"id\":\"202009150000001\",\"isCompany\":1,\"chapte\":[{\"page\":1,\"x\":0.65,\"y\":0.48}],\"number\":1},{\"id\":\"202007140000002\",\"isCompany\":0,\"chapte\":[{\"page\":1,\"x\":0.65,\"y\":0.18}],\"number\":2}]}";
        }
        log.info(template);
        log.info("盖章模板:{}", template);
        log.info("盖章token:{}", token);
        JSONObject contractParams = JSONUtil.parseObj(template);
        contractParams.put("contractNo", contractNo);
        log.info("盖章contractParams:{}", contractParams);
        String result = HttpUtil.createPost(fileContractPrimary)
                .header("Authorization", token)
                .body(contractParams.toString(), "application/json")
                .execute()
                .body();
        log.info("返回结果{}", result);
        return JSONUtil.toBean(result, JsonResult.class);
    }


    @Override
    public JsonResult officeAudit(String notaryNo, String status, String reason) {
        String token = getDzqToken();
        log.info("公证处审核结果通知客户端请求参数:{}", notaryNo.concat("-" + officeCode).concat("-" + status).concat("-" + reason));
        HttpResponse res = HttpRequest.post(updateStatusUrl)
                .header("Authorization", token)
                .header("Content-Type", "application/x-www-form-urlencoded")
//                    .header("Content-Type", "application/json;charset=utf-8")
                .form("notaryNo", notaryNo)
                .form("officeCode", officeCode)
                .form("status", status)
                .form("reason", reason)
                .execute();
        if (res.getStatus() == HttpStatus.SC_OK) {
            String result = UnicodeUtil.toString(res.body());
            com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(result);
            log.info("公证处审核结果通知客户端返回结果:{}", jsonObject.toJSONString());
            if (Objects.equals("200", jsonObject.get("code").toString())) {
                return JsonResult.success();
            }
            return JsonResult.fail();
        } else {
            return JsonResult.fail();
        }
    }

    @Override
    public JsonResult signContract(SignContractRequestDTO signContractRequestDTO) {
        String token = getDzqToken();
        String jsonStr = JSON.toJSONString(signContractRequestDTO);
        JsonResult config = sysPlatformOpeningRecordService.getConfig();
        ObjectMapper objectMapper = new ObjectMapper();
        SysConfig sysConfig = objectMapper.convertValue(config.getData(), SysConfig.class);
        String appId = "";
        String secret = "";
        if (sysConfig != null && StringUtils.isNotBlank(sysConfig.getAppid()) && StringUtils.isNotBlank(sysConfig.getSecret())) {
            appId = sysConfig.getAppid();
            secret = sysConfig.getSecret();
        }
        log.info("公证处发起文件签约参数:{}", jsonStr);
        log.info("发起合同路径：{}", signContractUrl);
        log.info("header {}", appId + "," + secret);
        String result = HttpUtil.createPost(signContractUrl)
                .header("Authorization", token)
                .header("appid", appId)
                .header("secret", secret)
                .body(jsonStr, "application/json")
                .execute()
                .body();
        log.info("公证处发起文件签约返回结果{}", result);
        return JSONUtil.toBean(result, JsonResult.class);
    }

    @Override
    public JsonResult createSigner(SignerRequestDTO signerRequestDTO) {
        String token = getDzqToken();
        String jsonStr = JSON.toJSONString(signerRequestDTO);
        log.info("请求地址:{}", createSignerUrl);
        log.info("个人开通签名参数:{}", jsonStr);
        String result = HttpUtil.createPost(createSignerUrl)
                .header("Authorization", token)
                .body(jsonStr, "application/json")
                .execute()
                .body();
        log.info("个人开通签名返回结果{}", result);
        return JSONUtil.toBean(result, JsonResult.class);
    }

    /**
     * 向盈诺签同步办证数据
     * @param notaryNo：卷宗号（必须）
     * @param type             类型（必选）0-核实函，1-执行证书, 2-公证书
     * @param file             文件路径 比如：https://xxx.com
     * @return
     */
    @Override
    public JsonResult updateCertificateFile(String notaryNo, String type, String file) {
        String token = getDzqToken();
        log.info("更新公证系统文件请求参数:{}", notaryNo.concat("-"+officeCode).concat("-"+type).concat("-"+file));
        HttpResponse res = HttpRequest.post(updateCertificateUrl)
                .header("Authorization", token)
                .header("Content-Type", "application/x-www-form-urlencoded")
//                    .header("Content-Type", "application/json;charset=utf-8")
                .form("notaryNo", notaryNo)
                .form("officeCode", officeCode)
                .form("type", type)
                .form("file", file)
                .execute();
        if (res.getStatus() == HttpStatus.SC_OK) {
            String result = UnicodeUtil.toString(res.body());
            com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(result);
            log.info("更新公证系统文件返回结果:{}", jsonObject.toJSONString());

            if (Objects.equals("200", jsonObject.get("code").toString())) {
                return JsonResult.success();
            }
            return JsonResult.success();
            // return JsonResult.fail();
        } else {
            return JsonResult.fail();
        }
    }

    @Override
    public JsonResult notaryRegister(GzcRegisterDTO gzcRegisterDTO) {
        log.info("公证处注册请求参数:{}", gzcRegisterDTO.toString());
        HttpResponse res = HttpRequest.post(notaryRegisterUrl)
                .header("Content-Type", "application/x-www-form-urlencoded")
                .form("account", gzcRegisterDTO.getMobile())//登录手机号码
                .form("password", gzcRegisterDTO.getPass())//登录密码
                .form("email", gzcRegisterDTO.getEmail())//邮箱账户
                .form("cardName", gzcRegisterDTO.getLegalPersonName())//法人身份证姓名
                .form("cardNo", gzcRegisterDTO.getLegalPersonIdNo())//法人身份证号码
                .form("companyName", gzcRegisterDTO.getGzcName())//企业名称
                .form("companyCode", gzcRegisterDTO.getGzcCode())//企业信用代码
                .form("cardImgFront", gzcRegisterDTO.getLegalIdCardFront())//法人身份证正面图片
                .form("cardImgBack", gzcRegisterDTO.getLegalIdCardBack())//法人身份证反面图片
                .form("business", gzcRegisterDTO.getOrganizationRegImg())//公司营业执照图片
                .execute();

        if (res.getStatus() == HttpStatus.SC_OK) {
            String result = UnicodeUtil.toString(res.body());
            com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(result);
            log.info("公证处注册返回结果:{}", jsonObject.toJSONString());
            if (Objects.equals("200", jsonObject.get("code").toString())) {
                return JsonResult.success(jsonObject.get("data"));
            }
            return JsonResult.fail();
        } else {
            return JsonResult.fail();
        }
    }

    @Override
    public JsonResult attestation(String unionid, String callBackUrl) {
        log.info("公证处认证请求参数:{},{}", unionid, callBackUrl);
        HttpResponse res = HttpRequest.post(attestationUrl)
                .header("Content-Type", "application/x-www-form-urlencoded")
                .form("unionId", unionid)//unuionid
                .form("callBackUrl", callBackUrl)//回调地址
                .execute();

        if (res.getStatus() == HttpStatus.SC_OK) {
            String result = UnicodeUtil.toString(res.body());
            com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(result);
            log.info("公证处认证返回结果:{}", jsonObject.toJSONString());
            if (Objects.equals("200", jsonObject.get("code").toString())) {
                return JsonResult.success();
            }
            return JsonResult.fail();
        } else {
            return JsonResult.fail();
        }
    }

    @Override
    public JsonResult verify(MultipartFile file, String hashCode, String originalHash) {
        log.info("存证校验请求参数:{},{},{}", file, hashCode, originalHash);
        HttpResponse res = null;
        try {
            if (file == null) {
                res = HttpRequest.post(verifyUrl)
                        .form("hashCode", hashCode)
                        .execute();
            } else {
                res = HttpRequest.post(verifyUrl)
                        .header("Content-Type", "multipart/form-data")
                        .form("file", file.getBytes(), "test.zip")
                        .execute();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (res.getStatus() == HttpStatus.SC_OK) {
            String result = UnicodeUtil.toString(res.body());
            com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(result);
            log.info("存证校验返回结果:{}", jsonObject.toJSONString());
            if (Objects.equals("200", jsonObject.get("code").toString())) {
                com.alibaba.fastjson.JSONObject resultObj = JSON.parseObject(jsonObject.get("data").toString());
                if (Objects.equals("200", resultObj.get("code").toString())) {
                    if (resultObj.getString("currentHash").equals(originalHash)) {
                        return JsonResult.success(resultObj);
                    } else {
                        return JsonResult.fail("该文件非原始文件！");
                    }
                }
                return JsonResult.fail(resultObj.get("message").toString());
            }
            return JsonResult.fail(jsonObject.get("message").toString());
        } else {
            return JsonResult.fail("校验文件失败！");
        }
    }

    @Override
    public InputStream download(MultipartFile file, String hashCode, String password) {
        Deposit deposit = depositService.getOne(Wrappers.<Deposit>query().eq("hash_code", hashCode));
        if (deposit != null) {
            password = deposit.getGrantKey();
        }
        log.info("存证下载请求参数:{},{},{}", file, hashCode, password);
        HttpResponse res = HttpRequest.post(downloadUrl)
                .header("Content-Type", "application/x-www-form-urlencoded")
                .form("file", file)
                .form("password", password)
                .form("hashCode", hashCode)
                .execute();
        log.info(res.toString());
        if (res.getStatus() == HttpStatus.SC_OK) {
            return res.bodyStream();
        }
        return null;
    }

    @Override
    public JsonResult getDepositList(Integer pageNum, Integer pageSize, DepositDTO depositDTO) {
        log.info("存证管理列表请求参数:{}", depositDTO.toString());
        HttpResponse res = HttpRequest.post(depositListUrl + "/" + pageNum + "/" + pageSize)
//                    .header("Content-Type", "application/x-www-from-urlencoded")
                .form("startTime", depositDTO.getStartTime())
                .form("endTime", depositDTO.getEndTime())
                .form("hash", StringUtils.isNotBlank(depositDTO.getHash()) ? depositDTO.getHash() : depositDTO.getBlockHash())
                .form("name", depositDTO.getName())
                .execute();
        if (res.getStatus() == HttpStatus.SC_OK) {
            String result = UnicodeUtil.toString(res.body());
            com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(result);
            log.info("存证管理列表返回结果:{}", jsonObject.toJSONString());
            if (Objects.equals("200", jsonObject.get("code").toString())) {
                return JsonResult.success(jsonObject);
            }
            return JsonResult.fail(jsonObject.get("message").toString());
        } else {
            return JsonResult.fail();
        }
    }

}
